#ifndef SINGLETON_H
#define SINGLETON_H
#include <memory>
#include <mutex>
#include <iostream>
using namespace std;

template <typename T>
class Singleton{
protected:
    // 默认构造函数，将其保护起来，防止外部直接实例化该类
    Singleton() = default;

    // 禁用拷贝构造函数，防止通过拷贝来创建新的对象，确保单例的唯一性
    Singleton(const Singleton<T>&) = delete;

    // 禁用赋值运算符，防止通过赋值操作来创建新的对象，确保单例的唯一性
    Singleton& operator=(const Singleton<T>& st) = delete;

    // 静态成员变量，用于存储单例对象的智能指针，初始化为 nullptr
    // 使用静态的 std::shared_ptr<T> _instance 是实现单例模式的关键，它保证了单例对象的全局唯一性、可访问性、生命周期管理以及线程安全的初始化。
    static std::shared_ptr<T> _instance;

public:
    static std::shared_ptr<T> GetInstance(){
        // 静态变量，用于确保单例对象只被创建一次
        static std::once_flag s_flag;

        // 使用 std::call_once 确保 lambda 表达式只被执行一次
        // 这样可以保证单例对象在多线程环境下也只被创建一次
        std::call_once(s_flag,[&](){
             // 在 lambda 表达式中创建单例对象，并使用 std::shared_ptr 进行管理
            _instance=shared_ptr<T>(new T);
        });
        return _instance;
    }

    // 成员函数，用于打印单例对象的内存地址
    void PrintAddress() {
        // 通过 get() 方法获取智能指针所管理的原始指针，并输出其地址
        std::cout << _instance.get() << endl;
    }

    // 析构函数，当单例对象被销毁时会调用该函数
    ~Singleton() {
        // 输出析构信息
        std::cout << "this is singleton destruct" << std::endl;
    }

};


// 模板类外初始化静态成员变量 _instance
template <typename T>
std::shared_ptr<T> Singleton<T>::_instance = nullptr;

#endif // SINGLETON_H
